// 多生产多消费
// 在这个场景下，无需修改代码！

// 构建任务2(给消费者派发任务，让消费者执行对应的任务)
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include "RingQueue.hpp"

struct threaddata
{
    RingQueue<int> *rq;
    std::string name;
};

// 消费者
void *consumer(void *args)
{
    threaddata *td = static_cast<threaddata*>(args);

    while (true)
    {
        sleep(3);
        // 1.消费任务
        //  sleep(1);
        int t = 0;
        td->rq->Pop(&t); // 进行构建任务并pop  队列拿任务

        // 2.处理任务 ---> 处理任务的时候，这个任务，已经被拿到线程的上下文中了，不属于队列了！
        std::cout << td->name << "消费者拿到了一个数据: " << t << std::endl;
        // t();      //进行执行对应任务
    }
}

// 生产者
void *productor(void *args)
{
    int data = 1;
    threaddata *td = static_cast<threaddata*>(args);
    while (true)
    {
        sleep(1);
        // 1.获得任务
        std::cout << td->name<< "生产了一个任务：" << data << std::endl;
        // 2.生产任务
        td->rq->Equeue(data);
        data++;
    }
}

int main()
{
    threaddata *td = static_cast<threaddata*>(td);

    // 申请阻塞队列
    RingQueue<int> *rq = new RingQueue<int>();

    /*
        单产单消:cc,pp（生产生产者，消费消费者之间）--> 互斥关系不需要维护，互斥与同步(用环形队列用信号量完成了生产者消费者
                两个线程之间的互斥与同步)     执行有先后（同步），访问同一个资源只能有一个线程访问（互斥）

        多产多消:cc,pp（生产生产者，消费消费者之间）-->  要完成生产者和消费者之间的互斥关系！！!
                互斥关系要维护，就要加锁
     */

    // 构建生产和消费者
    //  pthread_t c[1],p[1];     //单产单消

    pthread_t c[2], p[3];

    threaddata *td1 = new threaddata();
    td1->name = "cthread-1";
    td1->rq = rq;
    pthread_create(c, nullptr, consumer, td1);

    threaddata *td2 = new threaddata();
    td2->name = "cthread-2";
    td2->rq = rq;
    pthread_create(c + 1, nullptr, consumer, td2);

    threaddata *td3 = new threaddata();
    td3->name = "pthread-1";
    td3->rq = rq;
    pthread_create(p, nullptr, productor, td3);

    threaddata *td4 = new threaddata();
    td4->name = "pthread-2";
    td4->rq = rq;
    pthread_create(p + 1, nullptr, productor, td4);

    threaddata *td5 = new threaddata();
    td5->name = "pthread-3";
    td5->rq = rq;
    pthread_create(p + 2, nullptr, productor, td5);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);
    return 0;
}